#pragma once



#include "fxcc/core/graph/opengl3/pch.h"
#include "fxcc/core/graph/opengl3/RenderStateDesc.h"
#include "fxcc/core/graph/opengl3/Sampler.h"
#include "fxcc/core/graph/opengl3/InputLayout.h"
#include "fxcc/core/graph/opengl3/AttachmentTypeDesc.h"
#include "fxcc/core/graph/opengl3/IBuffers.h"

namespace fxcc
{
	namespace graph
	{
		namespace opengl3
		{
			struct FXCC_API DataTypeDesc
			{
				std::string m_Name;
				int m_Value;
			};
			struct FXCC_API IndexTypeDesc
			{
				std::string m_Name;
				int m_Target;
				int m_IndexStride;
			};
			struct FXCC_API VertexTypeDesc
			{
				std::string m_Name;
				int m_VertexStride;
				fxcc::graph::opengl3::InputLayout m_InputLayout;
			};

			struct FXCC_API ModeTypeDesc
			{
				std::string m_Name;
				int m_Target;
			};

			struct FXCC_API SamplerTypeDesc
			{
				std::string m_Name;
				fxcc::graph::opengl3::SamplerDesc m_SampDesc;
			};
			struct FXCC_API TextureTypeDesc
			{
				std::string m_Name;
				int m_Target;
			};
			struct FXCC_API FormatDesc
			{
				std::string m_Name;
				int m_Format;
				int m_InternalFormat;
				// 16F
				int m_HdrInternalFormat16F;
				// 32F
				int m_HdrInternalFormat32F;
			};

			struct FXCC_API RenderStates 
			{
				VertexTypeDesc m_VertexDescs[(int)common::VertexType::_vertex_end_];

				IndexTypeDesc m_IndexDescs[(int)common::IndexType::_index_end_];

				ModeTypeDesc m_ModeDescs[(int)common::ModeType::_mode_end_];

				DataTypeDesc m_DataTypeDescs[(int)common::DataType::_count_];

				SamplerTypeDesc m_SamplerDescs[(int)common::SamplerType::_count_];

				FormatDesc m_FormatDescs[5];

				SamplerTypeDesc GetSamplerTypeDesc(const fxcc::graph::common::SamplerType& type);

				VertexTypeDesc GetVertiexDesc(const common::VertexType& type);

				IndexTypeDesc GetIndexDesc(const common::IndexType type);

				ModeTypeDesc GetModeDesc(const common::ModeType& type);

				SamplerDesc GetSamplerLinearClamp();

				DepthStencilDesc m_DepthStencilDesc[(int)common::DepthStencilType::_END_];

				BlendDesc m_BlendDesc[(int)(common::BlendType::_END_)];

				RasterizerDesc m_RasterizerDesc[(int)(common::RasterizerType::_END_)];

				AttachmentTypeDesc m_AttachmentDescs[(int)fxcc::graph::common::AttachmentType::_Count_];

				std::shared_ptr<fxcc::graph::opengl3::IBuffers> m_Buffers;

				void Init();

				void InitBuffers();

				void InitAttachmentType();

				void InitBlendDesc();

				void InitRasterizerDesc();
				
				void InitDepthStencilDesc();

				void InitVertexDesc();

				void InitIndexDesc();

				void InitModeDesc();

				void InitDataTypeDesc();
				
				void InitFormatDesc();

				void InitSamplerDesc();

				int GetFormat(int numChannel);

				int GetInternalFomart(int numChannel, int hdr);

				void Clear(const fxcc::graph::common::RenderStateDesc& type);
				
				void SetSampler(int target, const fxcc::graph::common::SamplerType& type);

				fxcc::graph::opengl3::AttachmentTypeDesc GetAttachmentDesc(const fxcc::graph::common::AttachmentType &type);

				static std::shared_ptr<fxcc::graph::opengl3::IBuffers> GetBuffers();

			private:
				fxcc::graph::opengl3::InputLayout SkinnedVertexLayout();

				fxcc::graph::opengl3::InputLayout FixedVertexLayout();
			
			public:
				static RenderStates& Inst()
				{
					static RenderStates res;
					return res;
				};
			};
		}
	}
}